﻿Imports Org.BouncyCastle.X509
Imports SharedTools
Imports System.Xml.Serialization
Imports Org.BouncyCastle.Pkcs
Imports Org.BouncyCastle.Crypto
Imports Org.BouncyCastle.Asn1.Pkcs
Imports Org.BouncyCastle.Security
Imports Org.BouncyCastle.Math

Public Class CertificateItem
    Public Property Username As String
    Public Property ID As Integer
        Get
            If Certificate IsNot Nothing Then
                Return CInt(Certificate.SerialNumber.ToString)
            Else
                Return _OriginalRequestID
            End If
        End Get
        Set(value As Integer)
            _OriginalRequestID = value
        End Set
    End Property

    <XmlIgnore()> Public ReadOnly Property CertificateType As CertificateType
        Get
            Dim ext = Certificate.GetExtensionValue(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage)
            Dim ku As New Org.BouncyCastle.Asn1.X509.KeyUsage(X509KeyUsage.DigitalSignature)
            If ku.GetString = ext.ToString Then
                Return CertificateType.Signature
            Else
                Return SharedTools.CertificateType.Cryptography
            End If
        End Get
    End Property

    <XmlIgnore()> Public Property Certificate As X509Certificate
    Public Property SerializableCertificate As Byte()
        Get
            Try
                Return Certificate.GetEncoded
            Catch ex As Exception
                Return Nothing
            End Try
        End Get
        Set(value As Byte())
            Try
                Dim parser = New X509CertificateParser
                Certificate = parser.ReadCertificate(value)
            Catch ex As Exception
                Certificate = Nothing
            End Try
        End Set
    End Property

    <XmlIgnore()> Public Property OriginalRequest As Pkcs10CertificationRequest
    Public Property SerializableOriginalRequest As Byte()
        Get
            Try
                Return OriginalRequest.GetEncoded
            Catch ex As Exception
                Return Nothing
            End Try
        End Get
        Set(value As Byte())
            Try
                OriginalRequest = New Pkcs10CertificationRequest(value)
            Catch ex As Exception
                OriginalRequest = Nothing
            End Try
        End Set
    End Property
    Private _OriginalRequestID As Integer = -1

    Private _BouncyCastleKeypair As AsymmetricCipherKeyPair
    <XmlIgnore()> Public Property CertificateKey(pass As String) As AsymmetricCipherKeyPair
        Get
            If Not _IsPrivateKeyReady Or Not _IsPublicKeyReady Then
                Throw New ClientProfile.KeysNotReadyException
            End If
            Return New AsymmetricCipherKeyPair(PublicKeyFactory.CreateKey(SerializablePublicKey), PrivateKeyFactory.DecryptKey(pass.ToCharArray, SerializablePrivateKey))
        End Get
        Set(value As AsymmetricCipherKeyPair)
            Dim rand As New SecureRandom
            Dim arr As Byte() = New Byte(7) {}
            rand.NextBytes(arr)

            Dim privateKeyInfo As EncryptedPrivateKeyInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo("PBEwithSHA-1and3-keyDESEDE-CBC", pass.ToCharArray, arr, 3, value.Private)
            SerializablePrivateKey = privateKeyInfo.GetEncoded()

            Dim publicInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(value.Public)
            SerializablePublicKey = publicInfo.GetEncoded()
        End Set
    End Property

    Private ReadOnly Property _IsPrivateKeyReady As Boolean
        Get
            Return _SerializablePrivateKey IsNot Nothing
        End Get
    End Property
    Private ReadOnly Property _IsPublicKeyReady As Boolean
        Get
            Return _SerializablePublicKey IsNot Nothing
        End Get
    End Property


    Private _SerializablePrivateKey As Byte() = Nothing
    Public Property SerializablePrivateKey As Byte()
        Get
            Return _SerializablePrivateKey
        End Get
        Set(value As Byte())
            _SerializablePrivateKey = value
        End Set
    End Property

    Private _SerializablePublicKey As Byte() = Nothing
    Public Property SerializablePublicKey As Byte()
        Get
            Return _SerializablePublicKey
        End Get
        Set(value As Byte())
            _SerializablePublicKey = value
        End Set
    End Property
End Class
